home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-12-31 | 13.1 KB | 632 lines | [TEXT/CWIE] |
- // =================================================================================
- //
- // CPictControl.cpp ©1996 Microsoft Corporation All rights reserved.
- //
- // =================================================================================
-
- #include "ocheaders.h"
- #include "CPictControl.h"
- #include "CPictControlBSC.h"
- #include "CCFragResource.h"
- #include "CCurrentResource.h"
-
- #define CLICK_WAIT_TIME 30
- #define PICT_LINGER_TIME 5
- #define CYCLE_TIME_DLOG 128
- #define OK_BUTTON 1
- #define CANCEL_BUTTON 2
- #define LABEL_TEXT 3
- #define EDIT_TEXT 4
- #define MENU_ID 128
-
- const Uint32 DefaultIdleRefCon = 0;
-
- static Boolean8 FindUnusedMenuID(Int16 StartWithID, Int16 EndWithID, Int16 *FoundID);
- static Int16 GetPictCycleTime(Point CenterOn, Int16 CycleTime);
-
-
- #pragma mark === CPictsControl::Construction & Destruction ===
-
- //
- // CPictControl::CPictControl
- //
-
- CPictControl::CPictControl(void)
- {
- mPicts = NULL;
- mCurrentPict = 1;
- mCycleWaitTime = PICT_LINGER_TIME * 60;
- mAutoCycle = false;
- mOwnedFoci = EmptyFocusSet;
- }
-
- //
- // CPictControl::~CPictControl
- //
-
- CPictControl::~CPictControl(void)
- {
- if (mDataURLBuffer)
- {
- ::DisposeHandle(mDataURLBuffer);
- mDataURLBuffer = NULL;
- }
-
- if (mPicts)
- {
- for (Int16 i = 0; i < mPictCount; i++)
- {
- if (((*mPicts) + i)->Pic)
- ::DisposeHandle(Handle(((*mPicts) + i)->Pic));
- if (((*mPicts) + i)->BSC)
- ((*mPicts) + i)->BSC->Release();
- }
-
- ::DisposeHandle(Handle(mPicts));
- mPicts = NULL;
- }
- }
-
-
- #pragma mark === CPictControl::IControl ===
-
- //
- // CPictControl::IControl::Draw
- //
-
- STDMETHODIMP
- CPictControl::Draw(DrawContext* inContext)
- {
- if (inContext->DrawAspect != DVASPECT_CONTENT)
- return DV_E_DVASPECT;
-
- ::FrameRect(&inContext->Location);
-
- StringPtr ErrorMessage = NULL;
- if (mPicts)
- {
- pictinfo CurrentPict = *(*mPicts + mCurrentPict - 1);
- if (CurrentPict.Pic)
- {
- ::EraseRect(&inContext->Location);
- DrawPict(inContext->Port, &inContext->Location, CurrentPict.Pic, &CurrentPict.PicRect);
- }
- else if (CurrentPict.BSC)
- ErrorMessage = "\pPicture not loaded yet.";
- else
- ErrorMessage = "\pCouldn't fetch or store picture.";
- }
- else
- ErrorMessage = "\pNo pictures as parameters.";
-
- if (ErrorMessage)
- {
- // draw the error message
- ::TextFace(bold);
- ::TextFont(0);
- ::TextSize(12);
- ::MoveTo((inContext->Location.right + inContext->Location.left - StringWidth(ErrorMessage))/2,
- (inContext->Location.bottom + inContext->Location.top + 12)/2);
- ::DrawString(ErrorMessage);
- }
-
- return S_OK;
- }
-
-
- //
- // CPictControl:IControl:SetFocus
- //
- // Since we handle focus, we override the base class method for our needs
- //
-
- STDMETHODIMP
- CPictControl::SetFocus(FocusCommand inCommand, FocusSet inFocus)
- {
- ErrorCode ReturnValue = S_OK;
-
- // a TakeNext or TakePrev if we don't have the focus, means take it
- if ((inCommand == TakeNextCommand || inCommand == TakePrevCommand) &&
- !(mOwnedFoci & inFocus))
- {
- mOwnedFoci = FocusSet(mOwnedFoci | inFocus);
- }
- // a TakeNext or a TakePrev on a control which doesn't embed and has the focus should fail
- else if (inCommand == TakeNextCommand || inCommand == TakePrevCommand)
- {
- ReturnValue = E_FAIL;
- }
- // we're being asked/told to release our foci - always comply
- else // if (Spec == ReleaseRequest || Spec == ReleaseCommand)
- {
- if (inFocus & mOwnedFoci != inFocus)
- DebugStr("\pWhat are they doing asking to release foci we don't have?");
-
- mOwnedFoci = FocusSet(mOwnedFoci & ~inFocus); // really easy for us
- }
-
- return ReturnValue;
- }
-
-
- //
- // CPictControl::IControl::DoMouse
- //
-
- STDMETHODIMP
- CPictControl::DoMouse(MouseEventType inMouseET, PlatformEvent* inEvent)
- {
- Boolean8 DoInval = false;
- Boolean8 DoAdvance = false;
-
- switch (inMouseET)
- {
-
- case MouseDown:
- {
- Boolean8 IsHoldDown;
- Int32 WaitTillTicks = inEvent->when + CLICK_WAIT_TIME;
-
- while (((IsHoldDown = ::WaitMouseUp()) != 0) && ::TickCount() < WaitTillTicks)
- ;
-
- if (IsHoldDown)
- {
- // for now we'll assume that we have a popup menu
- HandlePopUpMenuClick(inEvent->where);
- }
- else if (mPictCount)
- {
- AdvancePict();
-
- // since we just advanced the picture, reset the timer
- StartIdling();
- }
- }
- break;
- }
-
- return S_OK;
- }
-
-
- //
- // CPictsControl::IControl::DoIdle
- //
-
- STDMETHODIMP
- CPictControl::DoIdle(Uint32 IdleRefCon)
- {
- #pragma unused(IdleRefCon)
-
- AdvancePict();
-
- return S_OK;
- }
-
-
- #pragma mark === CPictControl::IPersist ===
-
- //
- // CPictControl::IPersistPropertyBag::IPersistPropertyBag::Load
- //
-
- STDMETHODIMP
- CPictControl::Load(IPropertyBag* PropertyBag, IErrorLog* ErrorLog)
- {
- Boolean8 KeepGoing = true;
- Char8 PropertyTag[10];
- ErrorCode ErrCode = S_OK;
- Int16 i = 0;
- VARIANT v;
-
- CBaseControl::Load(PropertyBag, ErrorLog);
-
- // dispose of the old url buffer if this is called multiple times
- if (mDataURLBuffer)
- {
- ::DisposeHandle(mDataURLBuffer);
- mDataURLBuffer = NULL;
- }
-
- v.vt = VT_BSTR;
- v.bstrVal = NULL;
-
- // try to load in the property. if we can't get it, then leave
- // things at their default.
- //
- while (KeepGoing)
- {
- ::BlockMove("data", PropertyTag, 5);
-
- if (++i != 1)
- {
- Uchar8 NumString[5];
- ::NumToString(i, NumString);
- ::BlockMove(NumString + 1, PropertyTag + 4, *NumString);
- PropertyTag[4 + *NumString] = '\0';
- }
-
- KeepGoing = PropertyBag->Read(PropertyTag, &v, ErrorLog) == S_OK && v.bstrVal;
- if (KeepGoing)
- {
- Uint32 DataLength = *((Uint32*) v.bstrVal);
- Uint32 BufferSize;
-
- if (!mDataURLBuffer)
- {
- BufferSize = 0;
- mDataURLBuffer = ::NewHandle(0);
- }
- else
- BufferSize = ::GetHandleSize(mDataURLBuffer);
-
- if (mDataURLBuffer)
- {
- ::SetHandleSize(mDataURLBuffer, BufferSize + DataLength + 1);
- if (::MemError() != noErr)
- ErrCode = E_FAIL;
- }
-
- if (ErrCode == S_OK)
- {
- ::HLock(mDataURLBuffer);
- ::BlockMove( v.bstrVal + sizeof(Uint32), *mDataURLBuffer + BufferSize, DataLength);
- *(*mDataURLBuffer + BufferSize + DataLength) = '\0';
- ::HUnlock(mDataURLBuffer);
- CoTaskMemFree(v.bstrVal);
- }
- }
- }
-
- // if LoadTextState loaded up our data buffer then open streams
- if (mDataURLBuffer)
- {
- Char8 *CurrentURL, *EndChar;
- Int32 CurrentPosition = 0;
-
- ::HLock(mDataURLBuffer);
- CurrentURL = *mDataURLBuffer;
- EndChar = *mDataURLBuffer + ::GetHandleSize(mDataURLBuffer);
-
- // start up a BSC for each url we loaded
- while (CurrentURL < EndChar && ErrCode == S_OK)
- {
- // if we haven't allocated a handle for picture info then allocate it
- if (!mPicts)
- mPicts = (pictinfo**)::NewHandle(0);
-
- // if we have allocated a handle then grow it by one
- if (mPicts)
- {
- ::SetHandleSize(Handle(mPicts), (mPictCount + 1) * sizeof(pictinfo));
- if (::MemError() == noErr)
- {
- pictinfo* PictInfo;
-
- ::HLock(Handle(mPicts));
- PictInfo = (*mPicts + mPictCount);
- AddRef(); // account for this pointer being sent to bsc
- PictInfo->BSC = new CPictControlBSC(this, Uint32(mPictCount + 1));
- PictInfo->Pic = NULL;
- if (PictInfo->BSC &&
- (ErrCode = PictInfo->BSC->OpenURL(mContainerSiteP, CurrentURL, false)) != S_OK)
- {
- PictInfo->BSC->Release();
- PictInfo->BSC = NULL;
- }
- ::HUnlock(Handle(mPicts));
- mPictCount++;
- }
- }
-
- while (*CurrentURL++)
- ;
-
- }
- ::HUnlock(mDataURLBuffer);
-
- // we don't need to keep the url's around after we load them
- ::DisposeHandle(mDataURLBuffer);
- mDataURLBuffer = NULL;
- }
-
- return ErrCode;
- }
-
-
- #pragma mark === CPictControl CBaseControl override methods ===
-
- //
- // CPictControl::StartIdling
- //
-
- Boolean8
- CPictControl::StartIdling(void)
- {
- Boolean8 ReturnResult = false;
-
- if (mAutoCycle)
- ReturnResult = mContainerSiteP->SetIdleTime(mCycleWaitTime, DefaultIdleRefCon) == S_OK;
-
- return ReturnResult;
- }
-
-
- //
- // CPictControl::StopIdling
- //
-
- Boolean8
- CPictControl::StopIdling(void)
- {
- Boolean8 ReturnResult = false;
-
- ReturnResult = CBaseControl::StopIdling();
-
- return ReturnResult;
- }
-
-
- #pragma mark === CPictControl private methods ===
-
- //
- // CPictControl::DrawPict
- //
-
- void
- CPictControl::DrawPict(GrafPtr pGrafDraw, Rect* lprect, PicHandle Pic, Rect* PictRect)
- {
- #pragma unused (pGrafDraw)
- Rect theRect;
-
- theRect.top = lprect->top;
- theRect.left = lprect->left;
- theRect.bottom = lprect->top + PictRect->bottom;
- theRect.right = lprect->left + PictRect->right;
- ::DrawPicture(Pic, &theRect);
- }
-
-
- //
- // CPictControl::HandlePopUpMenuClick
- //
-
- Boolean8
- CPictControl::HandlePopUpMenuClick(PlatformPoint inEventLocation)
- {
- Int16 PopUpMenuID;
-
- // find an unused menu id - or don't do anything
- if (FindUnusedMenuID(MENU_ID, MENU_ID, &PopUpMenuID) ||
- FindUnusedMenuID(128, 2000, &PopUpMenuID))
- {
- CCFragResource CFragResourceSetter;
- CCurrentResource ResFileSetter(CFragResourceSetter.GetCFragResRefNum());
- Int32 MenuSelection;
- Point GlobalPt = inEventLocation;
- MenuHandle PopUpMenuH;
-
- // if there was a collision then push in the unique menu id
- // this is safe to do only because the menu is destroyed as soon
- // as we finish with it here
- PopUpMenuH = ::GetMenu(MENU_ID);
-
- // it is important to set the menu id ALWAYS, since the menu may have been
- // cached by the resource manager, so we get a "dirty" version with the
- // menu id used last time, which may not be valid this time
- (*PopUpMenuH)->menuID = PopUpMenuID;
-
- // add it into the menu bar
- ::InsertMenu(PopUpMenuH, hierMenu);
-
- // set the menu item state
- ::SetItemMark(PopUpMenuH, 1, mAutoCycle ? checkMark : 0);
-
- // do the popup thing
- MenuSelection = ::PopUpMenuSelect(PopUpMenuH, GlobalPt.v, GlobalPt.h, 1);
- switch (MenuSelection & 0x0000ffff)
- {
- case 1:
- mAutoCycle = !mAutoCycle;
- if (mAutoCycle)
- {
- AdvancePict(); // give immediate feedback that it worked
- StartIdling();
- }
- else
- StopIdling();
- break;
-
- case 2:
- // run a dialog to set m_CycleWaitTime
- Point CenterPt = { 200, 200 };
- if ((mOwnedFoci & ModalFocus) || (mContainerSiteP->RequestFocus(true, ModalFocus) == S_OK))
- {
- mCycleWaitTime = GetPictCycleTime(CenterPt, mCycleWaitTime / 60) * 60;
-
- if (!(mOwnedFoci & ModalFocus))
- mContainerSiteP->RequestFocus(false, ModalFocus);
- }
- else
- ::SysBeep(1);
- break;
-
- default:
- break;
- }
-
- // remove the popup and release it
- ::DeleteMenu(PopUpMenuID);
- ::ReleaseResource( Handle(PopUpMenuH) );
-
- }
-
- return false;
- }
-
-
- //
- // CPictControl::SetData
- //
- // our data input friend classes call this to insert data
- //
-
- void
- CPictControl::SetData(Handle InData, Uint32 PictIndex)
- {
- pictinfo* TempPictInfo;
-
- ::HLock(Handle(mPicts));
- TempPictInfo = *mPicts + PictIndex - 1;
- if (TempPictInfo->Pic)
- ::DisposeHandle(Handle(TempPictInfo->Pic));
- TempPictInfo->Pic = PicHandle(InData);
- if (InData)
- TempPictInfo->PicRect = (*(TempPictInfo->Pic))->picFrame;
- if (TempPictInfo->BSC)
- {
- TempPictInfo->BSC->Release();
- TempPictInfo->BSC = NULL;
- }
- ::HUnlock(Handle(mPicts));
-
- if (mCurrentPict == PictIndex)
- {
- mCurrentPict--; // decrement this so we can advance to it
- AdvancePict();
- }
- }
-
-
- //
- // CPictControl::AdvancePict
- //
- // advance the displayed pict
- //
-
- void
- CPictControl::AdvancePict(void)
- {
- Int16 PrevPict = mCurrentPict++;
- // move current picture forward
- if (mCurrentPict > mPictCount)
- mCurrentPict = 1;
-
- if (PrevPict != mCurrentPict)
- mContainerSiteP->OnChange(ViewChange);
-
- // adjust the size if it is needed
- Boolean8 Adjusted = false;
- Int32 i;
- pictinfo CurrentPict = *(*mPicts + mCurrentPict - 1);
-
- if ((i = CurrentPict.PicRect.bottom - CurrentPict.PicRect.top) > mSize.v)
- {
- Adjusted = true;
- mSize.v = i;
- }
-
- if ((i = CurrentPict.PicRect.right - CurrentPict.PicRect.left) > mSize.h)
- {
- Adjusted = true;
- mSize.h = i;
- }
-
- if (Adjusted)
- mContainerSiteP->RequestSizeChange(&mSize);
-
- // force a redraw
- InvalAllContexts();
- }
-
-
- #pragma mark === CPictControl Statics ===
-
- //
- // FindUnusedMenuID
- //
-
- Boolean8
- FindUnusedMenuID(Int16 StartWithID, Int16 EndWithID, Int16 *FoundID)
- {
- Boolean8 Found = false;
-
- while (StartWithID <= EndWithID && !Found)
- {
- if ((Found = (GetMHandle(StartWithID++) == NULL)) == true)
- *FoundID = StartWithID - 1;
- }
-
- return Found;
- }
-
-
- //
- // GetPictCycleTime
- //
-
- Int16
- GetPictCycleTime(Point CenterOn, Int16 CycleTime)
- {
- #pragma unused (CenterOn)
- CCFragResource CFragResourceSetter;
- CCurrentResource ResFileSetter(CFragResourceSetter.GetCFragResRefNum());
- DialogPtr DlogPtr;
-
- if ((DlogPtr = ::GetNewDialog(CYCLE_TIME_DLOG, NULL, (WindowPtr) -1)) != 0)
- {
- Boolean8 Done;
- Handle ItemHandle;
- Int16 ItemHit;
- Str255 TextStr;
-
- // tell the dialog manager the behavior we want
- ::SetDialogDefaultItem(DlogPtr, OK_BUTTON);
- ::SetDialogCancelItem(DlogPtr, CANCEL_BUTTON);
- ::SetDialogTracksCursor(DlogPtr, true);
-
- {
- Rect TRect;
- Int16 Type;
-
- ::GetDItem(DlogPtr, EDIT_TEXT, &Type, &ItemHandle, &TRect);
- ::NumToString(CycleTime, TextStr);
- ::SetIText(ItemHandle, TextStr);
- ::SelIText(DlogPtr, EDIT_TEXT, 0, 32767);
- }
-
- do
- {
- ::ModalDialog(0, &ItemHit);
- switch (ItemHit)
- {
- case OK_BUTTON:
- {
- Int32 TempTime;
-
- ::GetIText(ItemHandle, TextStr);
- ::StringToNum(TextStr, &TempTime);
- if (TempTime > 0)
- CycleTime = TempTime;
- }
- // intentional fall through
-
- case CANCEL_BUTTON:
- Done = true;
- break;
-
- default:
- Done = false;
- break;
- }
- }
- while (!Done);
-
- ::DisposeDialog(DlogPtr);
- }
-
- return CycleTime;
- }
-
-